package cmd

import (
	"fmt"
	"net"
	"path/filepath"
	"time"

	"gitee.com/zfd81/dbrs/cluster"

	"gitee.com/zfd81/dbrs/sys"

	"gitee.com/zfd81/dbrs/proto"

	pb "gitee.com/zfd81/dbrs/proto/dbrspb"

	"google.golang.org/grpc"

	"github.com/fatih/color"

	"gitee.com/zfd81/dbrs/server"
	"gitee.com/zfd81/dbrs/server/auth"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"golang.org/x/sync/errgroup"
)

var (
	g       errgroup.Group
	address string
	port    uint32
)

func NewStartCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "start",
		Short: "Start databroker service",
		Run:   startCommandFunc,
	}

	//设置命令行参数
	cmd.Flags().StringVar(&address, "addr", conf.Address, "Network address to run the server")
	cmd.Flags().Uint32Var(&port, "p", conf.Port, "Port to run the server")

	return cmd
}

func startCommandFunc(cmd *cobra.Command, args []string) {
	//打印Banner
	color.Green(conf.Banner)

	//根据命令行参数修改配置信息
	conf.Address = address
	conf.Port = port

	//打印配置信息
	logrus.Info("Databroker server version: ", conf.Version)
	logrus.Info("Databroker server log level: ", conf.Log.Level)

	abs, _ := filepath.Abs(conf.Log.Path)
	logrus.Info("Databroker server log file path: ", filepath.Join(abs, "logs"))

	abs, _ = filepath.Abs(conf.DataDirectory)
	logrus.Info("Databroker server data file path: ", filepath.Join(abs, "data"))

	sys_auth := auth.NewNativeSingle()
	users, err := sys.FindAllUsers()
	if err != nil {
		logrus.Fatalf("Failed to read user information: %v", err)
	}
	for _, user := range users {
		sys_auth.AddUser(user.Name, user.Password, auth.AllPermissions)
	}

	config := server.Config{
		Protocol: conf.Protocol,
		Address:  fmt.Sprintf("%s:%d", conf.Address, conf.Port),
		Auth:     sys_auth,
	}

	//创建RPC服务
	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", conf.ControlPort))
	if err != nil {
		logrus.Fatalf("failed to listen: %v", err)
	}
	controlServ := grpc.NewServer()
	pb.RegisterBrokerSystemServer(controlServ, &proto.BrokerSystem{})

	//启动控制Server
	g.Go(func() error {
		err := controlServ.Serve(lis)
		if err != nil {
			logrus.Errorf("failed to api serve: %v", err)
		}
		return err
	})

	serv, err := server.NewDefaultServer(config)
	if err != nil {
		logrus.Fatalf("failed to listen: %v", err)
	}

	//启动MySQL Server
	g.Go(func() error {
		err := serv.Start()
		if err != nil {
			logrus.Errorf("failed to start serve: %v", err)
		}
		return err
	})

	//集群注册
	err = cluster.Register()
	if err != nil {
		logrus.Fatalf("failed to start serve: %v", err)
	}

	//打印启动成功日志
	time.Sleep(time.Duration(1) * time.Second)
	logrus.Infof("Cluster listening on: %d", conf.Cluster.Port)
	logrus.Infof("Control service listening on: %d", conf.ControlPort)
	logrus.Infof("Databroker server started successfully, listening on: %s", config.Address)

	if err := g.Wait(); err != nil {
		logrus.Fatal(err)
	}
}
